package userserv

import (
	"codedef"
	"encoding/json"
	"fmt"
	"github.com/garyburd/redigo/redis"
	"log"
	"message"
	"net/http"
	"rhelper"
	"time"
)

// 删除注册的设备
func deleteDeviceFromRegister(cid string, uniqueId string, hid string) (error, int) {
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	accControllerStr, err := redis.String(rconn.Do("HGET", rhelper.UserHash+uniqueId, "controllers"))
	if err != nil {
		log.Println("get cid failed, get account controller string error:", err)
		return err, codedef.ERR_DATABASE
	}

	homeDevices, err := redis.String(rconn.Do("HGET", rhelper.HomeHash+hid, "devices"))
	log.Println("HGET", rhelper.HomeHash+hid, "devices")
	if err != nil {
		log.Println("get home devices failed, get home devices string error:", err)
		return err, codedef.ERR_DATABASE
	}

	accControllerStr = rhelper.CommaStringDelete(accControllerStr, cid)
	homeDevices = rhelper.CommaStringDelete(homeDevices, rhelper.ControllerHash+cid)
	log.Println(homeDevices)

	rconn.Send("MULTI")
	rconn.Send("HSET", rhelper.UserHash+uniqueId, "controllers", accControllerStr)
	rconn.Send("HSET", rhelper.HomeHash+hid, "devices", homeDevices)
	rconn.Send("HDEL", rhelper.ControllerHash+cid, "account", "alias", "remark", "homeId")
	_, err = rconn.Do("EXEC")
	if err != nil {
		log.Println("database error:", err)
		//replyError(w, codedef.ERR_DATABASE)
		return err, codedef.ERR_DATABASE
	}
	return nil, codedef.ERR_SUCCEED
}

/*
func deleteDeviceFromHome(cid string, hid string)error{
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	homeDevices , err := redis.String(rconn.Do("HGET",rhelper.HomeHash + hid ,"devices"))
	if err != nil {
		log.Println("get home devices failed, get home devices string error:", err)
		return err
	}

	homeDevices = rhelper.CommaStringDelete(homeDevices, cid)
	_,err = rconn.Do("HSET", rhelper.HomeHash + hid ,"devices", homeDevices)
	if err != nil{
		log.Println("database error:", err)
		//replyError(w, codedef.ERR_DATABASE)
		return err
	}
	return nil
}*/

// 删除共享的设备
func deleteDeviceFromShare(cid string, account string, uniqueId string) (error, int) {
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	accControllerStr, err := redis.String(rconn.Do("HGET", rhelper.UserHash+uniqueId, "controllers"))
	if err != nil {
		log.Println("get cid failed, get account controller string error:", err)
		return err, codedef.ERR_DATABASE
	}

	accControllerStr = rhelper.CommaStringDelete(accControllerStr, cid)

	shareAccountStr, err := redis.String(rconn.Do("HGET", rhelper.ControllerHash+cid, "shareAccount"))
	if err != nil && err != redis.ErrNil {
		log.Println("get device accout failed, get account controller string error:", err)
		return err, codedef.ERR_DATABASE
	}

	shareAccountStr = rhelper.CommaStringDelete(shareAccountStr, account)
	rconn.Send("MULTI")
	rconn.Send("HSET", rhelper.UserHash+uniqueId, "controllers", accControllerStr)
	rconn.Send("HSET", rhelper.ControllerHash+cid, "shareAccount", shareAccountStr)
	_, err = rconn.Do("EXEC")
	if err != nil {
		log.Println("database error:", err)
		//replyError(w, codedef.ERR_DATABASE)
		return err, codedef.ERR_DATABASE
	}

	return nil, codedef.ERR_SUCCEED

}

func loadControllerAccountFromDB(cid string) (acc string) {
	rconn := rhelper.Pool().Get()
	defer rconn.Close()

	acc, err := redis.String(rconn.Do("HGET", rhelper.ControllerHash+cid, "account"))
	if err != nil && err != redis.ErrNil {
		log.Println("get device accout failed, get account controller string error:", err)
		return
	}

	return acc
}

func onDelDevice(w http.ResponseWriter, r *http.Request) {
	var uniqueId string
	uniqueId = r.Header.Get("uniqueId")

	log.Printf("onDevRequest, uniqueId:%s\n", uniqueId)

	type DelDeviceRequest struct {
		ControllerId string `json:"cid"`
		Account      string `json:"account"`
		HomeId       string `json:"homeId"`
	}

	if r.ContentLength < 1 {
		log.Println("onDelDevice failed, content length is zero")
		replyError(w, codedef.ERR_REQUEST_INVALID_PARAM)
		return
	}

	rmessage := make([]byte, r.ContentLength)
	n, _ := r.Body.Read(rmessage)
	if n != int(r.ContentLength) {
		log.Println("onDelDevice failed, can't read request body")
		replyError(w, codedef.ERR_REQUEST_INVALID_PARAM)
		return
	}
	log.Println("Receive message:", string(rmessage))
	var delDeviceRequest DelDeviceRequest
	err := json.Unmarshal(rmessage, &delDeviceRequest)
	if err != nil {
		log.Println("onDelDevice failed, json decode failed:", err)
		replyError(w, codedef.ERR_DECODE)
		return
	}

	if delDeviceRequest.ControllerId == "" {
		log.Println("onDelDevice failed, controller id is empty")
		replyError(w, codedef.ERR_REQUEST_INVALID_PARAM)
		return
	}

	if delDeviceRequest.HomeId == "" {
		log.Println("onDelDevice failed, home id is empty")
		replyError(w, codedef.ERR_REQUEST_INVALID_PARAM)
		return
	}

	/*
		if !isUserDeviceExist(uniqueId, delDeviceRequest.ControllerId) {
			log.Println("onDelDevice failed, controller not exist ", delDeviceRequest.ControllerId)
			replyError(w, codedef.ERR_CONTROLLER_NOT_EXIST)
			return
		}*/

	msgUsers, err := getHomeMemberUserIds(delDeviceRequest.HomeId)
	if err != nil {
		log.Println("get home member user ids failed, err:", err)
		return
	}
	adminInfo, err := getUserInfoById(msgUsers[0])
	if err != nil {
		log.Println("get userinfo failed, err:", err)
		return
	}
	ownerInfo, err := getUserInfoById(uniqueId)
	if err != nil {
		log.Println("get userinfo failed, err:", err)
		return
	}

	acc := loadControllerAccountFromDB(delDeviceRequest.ControllerId)
	if acc != delDeviceRequest.Account {
		err, errorCode := deleteDeviceFromShare(delDeviceRequest.ControllerId, delDeviceRequest.Account, uniqueId)
		if err != nil {
			replyError(w, errorCode)
		}

		controller := Controller{}
		controller.Id = delDeviceRequest.ControllerId

		replyJSON(w, controller)

		msgTitle := fmt.Sprintf("%s removed the air purifier from %s's home", ownerInfo[0], adminInfo[0])
		msgs := message.GenerateMessages(msgUsers, "1", ownerInfo[1], msgTitle, "", 0)
		go message.SendMessage(msgs, "devMessage")

		return
	}

	deleteDeviceFromRegister(delDeviceRequest.ControllerId, uniqueId, delDeviceRequest.HomeId)
	//deleteDeviceFromHome(delDeviceRequest.ControllerId, homeId)

	controller := getOnlineControllerById(delDeviceRequest.ControllerId)
	if controller == nil {
		//log.Println("onDelDevice, delete controller failed, controller offline")
		//replyError(w, codedef.ERR_CONTROLLER_OFFLINE)
		controller := Controller{}
		controller.Id = delDeviceRequest.ControllerId
		replyJSON(w, controller)
		return
	}

	if controller.isBusy() {
		log.Println("onDelDevice failed, controller is busy:", controller.Id)
		replyError(w, codedef.ERR_CONTROLLER_BUSY)
		return
	}

	type DelDevice struct {
		URI string `json:"uri"`
		//ControllerId string
	}
	var delDevice = DelDevice{}
	delDevice.URI = "/delDevice"
	//delDevice.ControllerId = controller.Id

	wait := make(chan []byte, 1)
	controller.writeJSONWait(delDevice, wait)
	select {
	case reply := <-wait:
		_, errCode := parserDevReply(reply)
		if errCode != 0 {
			replyError(w, errCode)
			return
		}

		controller.closeDevWebSocket()
		replyJSON(w, controller)
		msgTitle := fmt.Sprintf("%s removed the air purifier from %s's home", ownerInfo[0], adminInfo[0])
		msgs := message.GenerateMessages(msgUsers, "1", ownerInfo[1], msgTitle, "", 0)
		go message.SendMessage(msgs, "devMessage")

		break
	case <-time.After(time.Second * 30):
		controller.giveupWaitAndDiscard()
		replyError(w, codedef.ERR_CONTROLLER_NO_RESPONSE)
		log.Println("user request device timeout")
		break
	}
}

func init() {
	myMux.muxHandlers.HandleFunc("/delDevice", onDelDevice)
}
